/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "3D视口工作区.h"


#include "A_引擎/引擎.h"
#include "B_场景管理/相机/相机控制.h"
#include "物体编辑/3D控制手柄.h"
#include "物体编辑/物体编辑.h"
#include "异步解算/物理异步解算.h"

#include "../ui属性栏.h"
#include "../ui节点面板.h"
#include "../ui节点视口.h"
#include "../节点视口/ui节点创建菜单.h"


#include "ui3D场景视口.h"



#include <几何图形/图形相交.h>
#include <节点/空间/场景信息.h>



static std::vector<S_物体*> g_当前操作物体;

static C_Widget* m_3D视口创建弹出菜单 = nullptr;
static C_Widget* m_3D视口插帧弹出菜单 = nullptr;
static bool g多选物体 = false;



static vec3		g射线相交点位置 = {};
static vec3		g手柄轴方向 = {};
static float32	g视线方向初始角度_X;
static float32	g视线方向初始角度_Y;
static vec2     g鼠标开始位置 = {};




//static S_Props g变换开关 = f_alloc_bool_1DProp(3, L"变换");


Inline void f_取消变换操作(S_摄像机* camera) {
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	switch (S_框架::g_变换方式) {
	case E_变换::e_移动:
		f_控制手柄_取消移动物体(camera);
		break;
	case E_变换::e_旋转:
		f_控制手柄_取消旋转物体();
		break;
	case E_变换::e_缩放:
		f_控制手柄_取消缩放物体();
		break;
	}
}

static void f_开始拾取点初始化(S_摄像机* camera, const vec2& 鼠标局部位置, const S_Rect2Df& rect) {
	vec3 坐标 = { 鼠标局部位置.x, 鼠标局部位置.y, 0.0f };
	vec3 当前射线[2];
	当前射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
	坐标.z = 1.0;
	当前射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
	S_射线拾取参数::g结束射线 = vec_normalize2(当前射线[1] - 当前射线[0]);

	vec3 视线向量 = f_camera_get视线向量(camera); //S_Core::g_视线向量;
	switch (S_框架::g_变换轴) {
	case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
	case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
	case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;
	default:
		break;
	}
	vec_normalize(视线向量);

	f_graph_射线相交平面(当前射线[0] - S_射线拾取参数::g手柄位置, 当前射线[1] - S_射线拾取参数::g手柄位置, 视线向量, S_射线拾取参数::g交点S);
}


static bool f_鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {
	//C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	auto camera = f_ui_get3D视口摄像机(self);

	switch (按钮) {
	case E_鼠标按钮::e_鼠标左键: {
		C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_鼠标左键;
		C_3D场景视口::g鼠标左键是否按下 = true;
		//std::cout << "f_鼠标按下:" << g视口摄像机旋转 << " = " << S_框架::g_变换轴 << std::endl;
		if (!C_3D场景视口::g视口摄像机旋转) {
			S_框架::g_变换开关 = true;
			//S_射线拾取参数::g手柄位置 = S_框架::g_变换手柄->f_get位置();

			switch (S_框架::g_变换方式) {
			case E_变换::e_移动:
				f_控制手柄_准备移动物体();
				break;
			case E_变换::e_旋转:
				f_控制手柄_准备旋转物体(f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self), self->f_getRect(), camera);
				break;
			case E_变换::e_缩放:
				f_控制手柄_准备缩放物体(f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self), self->f_getRect(), camera);
				break;
			default:
				break;
			}
		}

		//设置互交视口拾取射线;
		if (f_prop_Bool(S_节点数据::g_物理引擎视口互交)) {
			float32 最近坐标 = 1e+7;
			auto scene = f_NodeCtx_get默认场景();
			auto obs = f_scene_射线拾取(scene, S_节点数据::g_视口鼠标点射线[0], S_节点数据::g_视口鼠标点射线[1], &最近坐标);
			if (obs.size()) {
				
				S_节点数据::g_视口物理互交参数.bodyID = obs.front()->m_ID;
				S_节点数据::g_视口物理互交参数.pos = S_节点数据::g_视口鼠标点射线[0] + vec_normalize(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]) * 最近坐标;
				S_节点数据::g_视口物理互交参数.dis = 最近坐标;
				S_节点数据::g_视口物理互交参数.vec = {};
			}
			else {
				S_节点数据::g_视口物理互交参数.bodyID = -1;
			}
		}
	}
	break;
	case E_鼠标按钮::e_鼠标中键: {
		C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_鼠标中键;
		//S_Core::g_视线向量 = f_camera_get视线向量(S_Core::g_相机);
	}
	break;
	case E_鼠标按钮::e_鼠标右键:
		/*if (S_框架::g_变换开关) {
			S_框架::g_变换开关 = false;
			f_取消变换操作(camera);
		}*/
		break;
	}

	S_框架::g_鼠标起始坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	//std::cout << "f_鼠标按下:" << w << " = " << std::endl;
	return false;
}

static bool f_鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	C_工作区页面* page = static_cast<C_工作区页面*>(view->m_父部件);
	auto camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	switch (按钮) {
	case E_鼠标按钮::e_鼠标左键:
		C_3D场景视口::g视口摄像机平移 &= (C_3D场景视口::g_移动视口_键盘按键 | C_3D场景视口::g_移动视口_鼠标中键);
		C_3D场景视口::g鼠标左键是否按下 = false;
		

		if (S_框架::g_变换开关) {
			//S_Core::g_变换方式 = E_变换::e_变换_None;
			if (S_框架::g_变换方式 == E_变换::e_移动) {
				f_控制手柄_完成移动物体(camera);
				break;
			}
			if (S_框架::g_变换方式 == E_变换::e_旋转) {
				f_控制手柄_完成旋转物体();
				break;
			}
			if (S_框架::g_变换方式 == E_变换::e_缩放) {
				f_控制手柄_完成缩放物体();
				break;
			}

			//C_3D场景视口::g视口摄像机平移 = 0;
		}
		

		view->m_是否开启视线旋转物体 = true;
		break;

	case E_鼠标按钮::e_鼠标中键: {
		C_3D场景视口::g视口摄像机平移 &= (C_3D场景视口::g_移动视口_鼠标左键 | C_3D场景视口::g_移动视口_键盘按键);

		break;
	}
	
	case E_鼠标按钮::e_鼠标右键: {
		
		break;
	}

	}

	S_框架::g_变换开关 = false;
	S_框架::g_变换轴 = E_轴向::e_None轴向;
	S_节点数据::g_视口物理互交参数.bodyID = -1;

	view->f_关闭虚拟线绘制();
	view->m_是否开启视线旋转物体 = false;
	f_控制手柄_轴线显示(E_轴向::e_XYZ);
	return false;
}


static bool f_鼠标位置改变(C_Widget* self, const ivec4& mouse) {
	static vec2 轴线 = { 1,0 };
	
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	C_工作区页面* page = static_cast<C_工作区页面*>(view->m_父部件);
	auto camera = f_ui_get3D视口摄像机(view->ui_三维视口);
	auto rect = f_ui_get视口(view->ui_三维视口);
	//std::cout << "移动长度A = " << " " << " x:" << int32(g手柄拾取的轴) << std::endl;
	auto pos = f_widget_get鼠标局部位置((vec2{ float32(mouse.x), float32(mouse.y) }), view->ui_三维视口);
	vec3 坐标 = { pos.x, pos.y, 0.001f };

	if (S_框架::g_变换轴 != E_轴向::e_None轴向 < 0 && C_3D场景视口::g鼠标左键是否按下 && !C_3D场景视口::g视口摄像机平移) {
		if (f_prop_Bool(S_节点数据::g_物理引擎视口互交)) {
			
			if (camera->m_投影模式 == E_投影模式::e_透视) {
				S_节点数据::g_视口鼠标点射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
				坐标.z = 1.0;
				S_节点数据::g_视口鼠标点射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
			}
			else {
				坐标.z = -1.0;
				S_节点数据::g_视口鼠标点射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
				坐标.z = 1.0;
				S_节点数据::g_视口鼠标点射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
			}

			vec3 新远端坐标 = S_节点数据::g_视口鼠标点射线[0] + (vec_normalize(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]) * S_节点数据::g_视口物理互交参数.dis);
			//S_节点数据::g_视口物理互交参数.vec = 新远端坐标 - S_节点数据::g_视口物理互交参数.pos;
			S_节点数据::g_视口物理互交参数.vec = 新远端坐标 - S_节点数据::g_视口物理互交参数.pos;
			return false;
		}
	}


	if (S_框架::g_变换开关) {
		switch (S_框架::g_变换方式) {
		case E_变换::e_移动 : {
			vec3 视线向量 = f_camera_get视线向量(camera);

			vec3 当前射线[2];
			当前射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
			坐标.z = 1.0;
			当前射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
			S_射线拾取参数::g结束射线 = vec_normalize2(当前射线[1] - 当前射线[0]);


			if (S_框架::g_变换轴 == E_轴向::e_XYZ) {
				f_graph_射线相交平面(当前射线[0] - S_射线拾取参数::g手柄位置, 当前射线[1] - S_射线拾取参数::g手柄位置, 视线向量, S_射线拾取参数::g交点E);
				f_控制手柄_移动物体(S_射线拾取参数::g手柄位置 + S_射线拾取参数::g交点E - S_射线拾取参数::g交点S);
				f_页面_更新联动工作区(E_工作区类型::e_3D视口);
			}
			else {
				switch (S_框架::g_变换轴) {
				case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
				case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
				case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;
				default:
					break;
				}
				vec_normalize(视线向量);
				f_graph_射线相交平面(当前射线[0] - S_射线拾取参数::g手柄位置, 当前射线[1] - S_射线拾取参数::g手柄位置, 视线向量, S_射线拾取参数::g交点E);

				vec3 倾斜向量 = S_射线拾取参数::g交点E - S_射线拾取参数::g交点S;
				float32 移动距离 = 0;
				switch (S_框架::g_变换轴) {
				case E_轴向::e_X: 移动距离 = 倾斜向量.x; break;
				case E_轴向::e_Y: 移动距离 = 倾斜向量.y; break;
				case E_轴向::e_Z: 移动距离 = 倾斜向量.z; break;
				default:
					break;
				}
				//std::cout << "移动长度 = " << S_Core::g_变换轴 << " " << uint32(g手柄拾取的轴) << std::endl;
				f_控制手柄_移动物体(S_射线拾取参数::g手柄位置 + g手柄轴方向 * 移动距离);
				f_页面_更新联动工作区(E_工作区类型::e_3D视口);
			}

			return false;
		}


		case E_变换::e_旋转: {
			vec3 视线向量;
			if (camera->m_投影模式 == E_投影模式::e_透视) {
				视线向量 = vec_normalize2(S_射线拾取参数::g手柄位置 - f_camera_get眼睛位置(camera));
			}
			else {
				视线向量 = f_camera_get视线向量(camera);
			}
			vec2 coord = f_Project空间坐标转屏幕(camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, S_射线拾取参数::g手柄位置, { self->m_Pos, self->m_Size });

			vec2 鼠标移动方向 = (pos - coord);
			float32 旋转弧度 = f_graph_两向量夹角弧度(vec_normalize2(鼠标移动方向), 轴线);
			if (鼠标移动方向.y < 0) 旋转弧度 = M_PI - 旋转弧度 + M_PI;
			

			view->f_旋转辅助线绘制(coord, 旋转弧度, vec_len(鼠标移动方向));

			float32 方向 = 1;
			switch (S_框架::g_变换轴) {
			case E_轴向::e_X: 
				if (vec_dot(视线向量, vec3{ 1, 0, 0 }) < 0) 方向 = -1;
				视线向量 = vec3{ 1, 0, 0 }; 
				break;
			case E_轴向::e_Y: 
				if (vec_dot(视线向量, vec3{ 0, 1, 0 }) < 0) 方向 = -1;
				视线向量 = vec3{ 0, 1, 0 }; 
				break;
			case E_轴向::e_Z: 
				if (vec_dot(视线向量, vec3{ 0, 0, 1 }) < 0) 方向 = -1;
				视线向量 = vec3{ 0, 0, 1 }; 
				break;
			default:
				break;
			}

			f_控制手柄_视线旋转物体(视线向量, 旋转弧度, 方向, camera);
			f_页面_更新联动工作区(E_工作区类型::e_3D视口);
			return false;
		}

		case E_变换::e_缩放: {
			vec3 中心坐标 = f_global_get激活物体中心点();
			vec2 coord = f_Project空间坐标转屏幕(camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, 中心坐标, { self->m_Pos, self->m_Size });
			vec2 鼠标移动方向 = (pos - coord);
			
			float32 旋转弧度 = f_graph_两向量夹角弧度(vec_normalize2(鼠标移动方向), 轴线);
			if (鼠标移动方向.y < 0) 旋转弧度 = M_PI - 旋转弧度 + M_PI;
			float32 缩放 = vec_len(鼠标移动方向);

			view->f_旋转辅助线绘制(coord, 旋转弧度, vec_len(鼠标移动方向));

			/*vec3 视线向量 = vec_normalize2(f_camera_get视线向量(camera));
			switch (S_框架::g_变换轴) {
			case E_轴向::e_X: 视线向量 = vec3{ 1, 0, 0 }; break;
			case E_轴向::e_Y: 视线向量 = vec3{ 0, 1, 0 }; break;
			case E_轴向::e_Z: 视线向量 = vec3{ 0, 0, 1 }; break;
			default:
				break;
			}*/
			
			f_控制手柄_局部缩放物体(S_框架::g_变换轴, 缩放);
			f_页面_更新联动工作区(E_工作区类型::e_3D视口);
			return false;
		}
		}
	}
	


	if (C_3D场景视口::g视口摄像机平移 == 3) {
		return true;
	}

	

	if (C_3D场景视口::g鼠标左键是否按下) {
		
	}
	else {
		f_camera_开始相机变换(camera);
		
		if (camera->m_投影模式 == E_投影模式::e_透视) {
			坐标.z = 0.01;
			S_节点数据::g_视口鼠标点射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
			坐标.z = 1.0;
			S_节点数据::g_视口鼠标点射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
		}
		else {
			auto rect = f_ui_get视口(self);
			坐标.z = -1.0;
			S_节点数据::g_视口鼠标点射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
			坐标.z = 1.0;
			S_节点数据::g_视口鼠标点射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, camera->m_相机位置矩阵, rect);
			S_射线拾取参数::g开始射线 = vec_normalize2(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]);

			float32 l = vec_len(S_射线拾取参数::g相机位置 - S_节点数据::g_视口鼠标点射线[0]);
			S_节点数据::g_视口鼠标点射线[0] = vec_add(S_节点数据::g_视口鼠标点射线[0], S_射线拾取参数::g开始射线 * l);
		}
		
		S_射线拾取参数::g开始射线 = vec_normalize2(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]);

		
		
		S_射线拾取参数::g手柄位置 = S_框架::g_变换手柄->f_get位置();
		S_射线拾取参数::g相机位置 = f_camera_get眼睛位置(camera);

		//std::cout<<"aa"<< S_射线拾取参数::g相机位置.x << std::endl;

		if (S_框架::g_变换手柄->m_渲染) {
			vec3 dir = vec_normalize2(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]);
			
			float32 dis = f_get相机到视点距离(camera) * 0.03;
			if (camera->m_投影模式 == E_投影模式::e_透视) {
				S_框架::g_变换轴 = f_拾取手柄轴(S_节点数据::g_视口鼠标点射线[0], dir, dis);
			}
			else {
				S_框架::g_变换轴 = f_拾取手柄轴(S_节点数据::g_视口鼠标点射线[0], dir, dis);
			}
			
			
			vec3 视线向量 = f_camera_get视线向量(camera);
			switch (S_框架::g_变换轴) {
			case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
			case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
			case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;
			default:
				break;
			}
			vec_normalize(视线向量);
			f_graph_射线相交平面(S_节点数据::g_视口鼠标点射线[0] - S_射线拾取参数::g手柄位置, S_节点数据::g_视口鼠标点射线[1] - S_射线拾取参数::g手柄位置, 视线向量, S_射线拾取参数::g交点S);

			S_Bounding lineBond = f_get移动控制手柄手柄最大长度(S_框架::g_变换轴);
			g手柄轴方向 = vec_normalize2(lineBond.max - lineBond.min);
			//f_控制手柄_准备移动物体();
		}
	}

	g鼠标开始位置 = f_widget_get鼠标局部位置((vec2{ float32(mouse.x), float32(mouse.y) }), self);
	

	return true;
}


static bool f_鼠标滚轮(C_Widget* self, const S_鼠标& 轮值) {
	//f_ob_set缩放(S_Core::g_旋转变换手柄, { dis, dis, dis });
	return true;
}


static bool on_3D视口键盘按键按下(C_Widget* self, const S_键盘& ks) {
	auto camera = f_ui_get3D视口摄像机(self);

	if (ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_按下) {
		C_3D场景视口::g视口摄像机旋转 = true;
	}
	else if (ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_放开 || ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_准备) {
		C_3D场景视口::g视口摄像机旋转 = false;
	}
	else {
		
	}


	if (ks.Keys状态[S_InputKey::e_KEY_左SHIFT] == DEF_按键状态_按下) {
		C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_键盘按键;
	}
	else if (ks.Keys状态[S_InputKey::e_KEY_左SHIFT] == DEF_按键状态_放开) {
		C_3D场景视口::g视口摄像机平移 &= (C_3D场景视口::g_移动视口_鼠标左键 | C_3D场景视口::g_移动视口_鼠标中键);
		g多选物体 = false;
	}





	if (S_节点数据::g_选中激活物体.size()) {
		switch (S_框架::g当前编辑对象类型) {
		case E_物体类型::t_网格: {
			f_view3d_物体编辑模式_键盘事件(ks);
			break;
		}
		case E_物体类型::t_骨架: 
		case E_物体类型::t_骨骼: {
			f_view3d_骨骼编辑模式_键盘事件(self, ks, *self->m_UIctx, camera);
			break;
		}
		
		case E_物体类型::t_摄像机: {
			break;
		}
		default:
			break;
		}
	}

	

	if (S_框架::g_变换开关) {
		auto camera = f_ui_get3D视口摄像机(self);

		if (ks.Keys状态[S_InputKey::e_KEY_X] == DEF_按键状态_按下) {
			S_框架::g_变换轴 = E_轴向::e_X;

			S_Bounding line = f_get移动控制手柄手柄最大长度(E_轴向::e_X);
			g手柄轴方向 = vec_normalize2(line.max - line.min);

			f_控制手柄_轴线显示(S_框架::g_变换轴);
			f_开始拾取点初始化(camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
		}
		if (ks.Keys状态[S_InputKey::e_KEY_Y] == DEF_按键状态_按下) {
			S_框架::g_变换轴 = E_轴向::e_Y;

			S_Bounding line = f_get移动控制手柄手柄最大长度(E_轴向::e_Y);
			g手柄轴方向 = vec_normalize2(line.max - line.min);

			f_控制手柄_轴线显示(S_框架::g_变换轴);
			f_开始拾取点初始化(camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
		}
		if (ks.Keys状态[S_InputKey::e_KEY_Z] == DEF_按键状态_按下) {
			S_框架::g_变换轴 = E_轴向::e_Z;

			S_Bounding line = f_get移动控制手柄手柄最大长度(E_轴向::e_Z);
			g手柄轴方向 = vec_normalize2(line.max - line.min);

			f_控制手柄_轴线显示(S_框架::g_变换轴);
			f_开始拾取点初始化(camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
		}

		return false;
	}
	


	if (f_KS(ks, S_InputKey::e_KEY_TAB) == DEF_按键状态_放开) {
		C_3D场景视口::g视口摄像机旋转 = false;
		f_ui_打开菜单(m_3D视口创建弹出菜单, C_Widget::g_鼠标.gPos);
	}


	return false;
}








C_工作区页面* f_工作区页面_3D视口create(S_UI创建环境& ctx) {
	auto* ui_视口 = new C_3D场景视口(ctx);
	auto ui_状态条 = new C_状态条(ctx);
	C_工作区页面* 工作区 = new C_工作区页面(E_工作区类型::e_3D视口, ctx, E_方向::e_横向, ui_视口, ui_状态条);


	ui_视口->mf_鼠标按键放开 = f_鼠标放开;
	ui_视口->mf_鼠标移动 = f_鼠标位置改变;

	ui_视口->ui_三维视口->mf_鼠标按键按下 = f_鼠标按下;
	ui_视口->ui_三维视口->mf_鼠标滚轮     = f_鼠标滚轮;
	ui_视口->ui_三维视口->mf_键盘按键敲击 = on_3D视口键盘按键按下;
	
	f_view3d_重构状态条(工作区->m_状态条, ui_视口->ui_三维视口);
	



	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, E_键位操作类型::e_键位_按下, f_工作区_移动物体, S_InputKey::e_KEY_G);
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, E_键位操作类型::e_键位_按下, f_工作区_旋转物体, S_InputKey::e_KEY_R);
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, E_键位操作类型::e_键位_按下, f_工作区_缩放物体, S_InputKey::e_KEY_S);


	S_拖拽键位映射* 拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_移动摄像机;
	拖放键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	拖放键位->键盘状态[0] = DEF_按键状态_按下中;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口->ui_三维视口;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)拖放键位);

	拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_移动摄像机;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_中键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口->ui_三维视口;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)拖放键位);

	拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_旋转摄像机;
	拖放键位->键盘按键[0] = S_InputKey::e_KEY_左ALT;
	拖放键位->键盘状态[0] = DEF_按键状态_按下中;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口->ui_三维视口;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)拖放键位);

	拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_物体数据编辑;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口->ui_三维视口;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)拖放键位);




	S_键盘键位映射* 快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_切换摄像机投影模式;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_5;
	快捷键->键盘状态[0] = DEF_按键状态_放开;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到激活物体中心;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_点;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到左;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_4;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到右;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_6;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到上;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_8;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到下;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_2;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_设置激活摄像机为视口摄像机;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_0;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);



	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_打开关键帧插入菜单;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_I;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	f_ui_注册键盘快捷键(ui_视口->ui_三维视口, 快捷键);



	S_鼠标键位映射* 鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_推拉摄像机;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui_视口->ui_三维视口;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_物体加选;
	鼠标键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	鼠标键位->键盘状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	鼠标键位->发生组件 = 工作区;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_物体单选;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	鼠标键位->发生组件 = 工作区;
	f_ui_注册鼠标快捷键(ui_视口->ui_三维视口, (S_键位映射*)鼠标键位);



	//鼠标键位 = f_widget_init_鼠标键位映射();
	//鼠标键位->event = f_工作区_选择物体;
	//鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	//鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	//鼠标键位->发生组件 = 工作区;
	//f_ui_注册鼠标快捷键(ui_三维视口->ui_三维视口, (S_键位映射*)鼠标键位);

    return 工作区;
}










void on_2级3D视口创建菜单项(C_Widget* self, const std::wstring name, uint16 id) {
	if (S_节点数据::g_物体节点树.size()) {
		C_节点树* t = (C_节点树*)(S_节点数据::g_物体节点树.front().m_Ptr);
		//on_NodeView_设置当前操作视口(t);
	}
	//S_MapPtr& 映射项 = f_prop_MapPrt(S_节点数据::g_物体节点树);
	f_NodeView_设置当前节点添加_树类型限制(E_节点树类型::e_type_物体节点树);

	f_NodeView_设置节点面板局部添加位置({});
	on_2级几何节点创建菜单项(self, name, id);
}

void on_2级3D视口创建物体项(C_Widget* self, const std::wstring name, uint16 id) {
	if (S_节点数据::g_物体节点树.size()) {
		C_节点树* t = (C_节点树*)(S_节点数据::g_物体节点树.front().m_Ptr);
		//on_NodeView_设置当前操作视口(t);
	}
	f_NodeView_设置当前节点添加_树类型限制(E_节点树类型::e_type_物体节点树);

	f_NodeView_设置节点面板局部添加位置({});
	on_2级物体节点创建菜单项(self, name, id);

	if (name == L"骨架") {
		f_NodeView_设置节点面板局部添加位置({});
		auto 骨架节点 = f_global_get激活节点();
		on_2级物体节点创建菜单项(self, L"骨头", id);
		auto 骨骼节点 = f_global_get激活节点();

		uint32 num = 骨架节点.size();
		assert(骨架节点.size() && 骨架节点.size() == 骨骼节点.size());
		for (uint32 i = 0; i < num; ++i) {
			auto ia = 骨骼节点[i]->m_包含在多个视口的UI部件.begin();
			auto ib = 骨架节点[i]->m_包含在多个视口的UI部件.begin();
			
			f_NodePlane_链接节点((C_节点面板*)*ia, 1, (C_节点面板*)*ib, 1);
		}
	}
}


static void on_1级创建菜单项(C_Widget* self, const std::wstring, uint16 id) {

}

static void on_1级菜单项_物体关键帧插入(C_Widget* self, const std::wstring name, uint16 id) {
	uint32 变换类型 = 0;

	if (name == L"移动") {
		变换类型 |= 1;
	} else if (name == L"旋转") {
		变换类型 |= 2;
	} else if (name == L"缩放") {
		变换类型 |= 4;
	}

	f_OE_物体变换插帧(变换类型);

	f_页面_更新联动工作区(E_工作区类型::e_3D视口);
}

void f_工作区页面_3D视口界面初始化(S_UI创建环境& ctx) {
	
	S_菜单创建参数 基本几何体创建参数 = {
		on_2级3D视口创建菜单项, {

			{L"平面", "", 0},
			{L"球体", "", 0},
			//{L"圆环", "", 0},
			{L"方体", "", 0},
			//{L"圆柱", "", 0},
			//{L"圆锥", "", 0},
			//{L"六面", "", 0},
			{L"线框立方体", "四边顶点", 0},
		}
	};

	S_菜单创建参数 骨骼创建参数 = {
		on_2级3D视口创建物体项, {
			{L"骨架",	"", 0},
			{L"IK",		"", 0},
		}
	};

	auto 灯光项 = f_menu参数_灯光();

	S_菜单创建参数 菜单创建参数 = {
		on_1级创建菜单项, {
			{L"网格", "三角网格", &基本几何体创建参数},
			//{L"骨骼", "bone", &骨骼创建参数},
			{L"灯光", "font-61452", &灯光项},
			//{L"物理", "orbital", &物理创建参数},
	}
	};

	m_3D视口创建弹出菜单 = f_ui_创建菜单(e_纵向, 菜单创建参数, ctx);


	S_菜单创建参数 关键帧菜单创建参数 = {
		on_1级菜单项_物体关键帧插入, {
			{L"移动", "font-475", 0},
			{L"旋转", "04", 0},
			{L"缩放", "top_right_expand", 0},
	}
	};
	m_3D视口插帧弹出菜单 = f_ui_创建菜单(e_纵向, 关键帧菜单创建参数, ctx);

}

void f_工作区_选择物体(C_工作区页面* 工作区页面, bool 是否加选) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(工作区页面->mui_画布页面);
	auto camera = f_ui_get3D视口摄像机(view->ui_三维视口);


	if (S_框架::g_变换开关) {
		f_取消变换操作(camera);
		S_框架::g_变换开关 = false;
		return ;
	}

	auto rect = f_ui_get视口(view->ui_三维视口);
	auto pos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, view->ui_三维视口);
	vec3 坐标 = { pos.x, pos.y, 0.0f };

	std::vector<vec3> 射线(2);
	if (camera->m_投影模式 == E_投影模式::e_透视) {
		射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
		坐标.z = 2.0;
		射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
	}
	else {
		坐标.z = -2.0;
		射线[1] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
		坐标.z = 2.0;
		射线[0] = f_UpProject还原空间顶点(坐标, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, rect);
		//std::cout << "坐标0" << 射线[0].x << " : " << 射线[0].y << " : " << 射线[0].z << std::endl;
		//std::cout << "坐标1" << 射线[1].x << " : " << 射线[1].y << " : " << 射线[1].z << std::endl;
	}
	
	


	if (f_prop_Bool(S_节点数据状态::g_打开编辑模式)) {
		if (S_节点数据::g_选中激活物体.size()) {
			S_框架::g当前编辑对象类型 = f_ob_get可视对象类型(S_节点数据::g_选中激活物体.front());

			switch (S_框架::g当前编辑对象类型) {
			case E_物体类型::t_网格: {
				if (f_prop_enum(S_节点数据状态::g_网格编辑模式)) {
					f_view3d_射线选中网格元素(射线[0], 射线[1], 是否加选, camera);
				}
				else {

				}
				break;
			}
			case E_物体类型::t_骨架:
			case E_物体类型::t_骨骼: {
				if (f_prop_enum(S_节点数据状态::g_骨骼编辑模式)) {
					f_view3d_射线选中骨骼元素(射线[0], 射线[1], 是否加选, camera);
				}
				else {

				}
				break;
			}

			case E_物体类型::t_摄像机: {
				break;
			}
			default:
				break;
			}
		}
	}
	else {
		f_view3d_射线选中物体(射线[0], 射线[1], 是否加选, camera);

		if (S_节点数据::g_选中激活物体.size()) {
			S_框架::g当前编辑对象类型 = f_ob_get可视对象类型(S_节点数据::g_选中激活物体.front());
			f_view3d_重构状态条(工作区页面->m_状态条, view->ui_三维视口);
			f_view3d_重构属性栏(工作区页面->m_属性栏, S_节点数据::g_选中激活物体, view->ui_三维视口);
		}
	}
}



E_事件是否传递 f_工作区_移动物体(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	auto* camera = f_ui_get3D视口摄像机(self);
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	S_框架::g_变换开关 = true;
	S_框架::g_变换轴 = E_轴向::e_XYZ;
	S_框架::g_变换方式 = E_变换::e_移动;
	S_框架::g_视线向量 = f_camera_get视线向量(camera);
	S_射线拾取参数::g手柄位置 = S_框架::g_变换手柄->f_get位置();

	S_框架::g_鼠标起始坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);


	if (f_prop_Bool(S_节点数据状态::g_打开编辑模式)) {
		switch (S_框架::g当前编辑对象类型) {
		case E_物体类型::t_网格: {
			goto To_移动;
			break;
		}
		case E_物体类型::t_骨架:
		case E_物体类型::t_骨骼: {
			if (f_prop_enum(S_节点数据状态::g_骨骼编辑模式) == E_骨骼编辑模式::e_姿态模式) {
				if (f_prop_enum(S_框架::g_骨骼姿态编辑模式) == 0) {
					f_工作区_旋转物体(self, 0);
					break;
				}
			}
			goto To_移动;
			break;
		}
		case E_物体类型::t_摄像机: {
			goto To_移动;
			break;
		}
		default:
			break;
		}
	}
	else {
	To_移动:
		f_开始拾取点初始化(camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
		f_控制手柄_准备移动物体();
	}

	
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_旋转物体(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	C_3D场景视口* view = static_cast<C_3D场景视口*>(self->m_父部件);
	if (view) {
		view->m_是否开启视线旋转物体 = true;
	}

	auto camera = f_ui_get3D视口摄像机(self);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();
	S_框架::g_变换开关 = true;
	S_框架::g_变换轴 = E_轴向::e_XYZ;
	S_框架::g_变换方式 = E_变换::e_旋转;

	S_射线拾取参数::g手柄位置 = f_global_get激活物体中心点();
	f_控制手柄_准备旋转物体(f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self), self->f_getRect(), camera);

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_缩放物体(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	auto camera = f_ui_get3D视口摄像机(self);
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	S_框架::g_变换开关 = true;
	S_框架::g_变换轴 = E_轴向::e_XYZ;
	S_框架::g_变换方式 = E_变换::e_缩放;

	f_控制手柄_准备缩放物体(f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self), self->f_getRect(), camera);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_旋转摄像机(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);
	//C_3D场景视口* view = static_cast<C_3D场景视口*>(self);

	f_ui_set3D视口默认摄像机(self);
	auto camera = f_ui_get3D视口摄像机(self);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	//std::cout << "C_Widget::g_鼠标.abs = " << move.x << " : " << move.x << std::endl;
	auto pos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	f_set相机旋转(camera, { C_Widget::g_鼠标.lPos.x * 0.7f, C_Widget::g_鼠标.lPos.y * 0.7f, 0.0f });

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_移动摄像机(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	auto camera = f_ui_get3D视口摄像机(self);
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto 局部位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);

	auto move = 局部位置 - S_框架::g_鼠标起始坐标;
	//std::cout << "C_Widget::g_鼠标.abs = " << move.x << " : " << move.x << std::endl;
	vec2 比例 = f_ui_get空间投影比例(f_ui_get视口(self), *camera);
	move.x /= 比例.x;
	move.y /= 比例.y;
	f_set相机平移(camera, move);

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_推拉摄像机(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	if (f_ui_set3D视口是否为默认摄像机(self)) {
		auto camera = f_ui_get3D视口摄像机(self);
		f_set相机距离(camera, C_Widget::g_鼠标.lZ);
	}
	else {

	}
	
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_切换摄像机投影模式(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	auto camera = f_ui_get3D视口摄像机(self);
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	if (camera->m_投影模式 == E_投影模式::e_正交) {
		camera->m_投影模式 = E_投影模式::e_透视;
	}
	else {
		camera->m_投影模式 = E_投影模式::e_正交;
	}
	camera->m_isUpdate = true;

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到激活物体中心(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	auto camera = f_ui_get3D视口摄像机(self);
	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	f_视口控制_镜头视点移动到激活物体中心(camera);
	return E_事件是否传递::e_事件传递_终止;
}


E_事件是否传递 f_工作区_镜头视点移动到左(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = 0;
	camera->m_变换.rotation.y = 90;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到右(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = 0;
	camera->m_变换.rotation.y = -90;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到上(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = -90;
	camera->m_变换.rotation.y = 0;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到下(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = 90;
	camera->m_变换.rotation.y = 0;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到前(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = 0;
	camera->m_变换.rotation.y = 0;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到后(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	S_框架::g_Scene->m_光追后端->f_重置渲染帧记录();

	auto camera = f_ui_get3D视口摄像机(self);
	camera->m_变换.rotation.x = 0;
	camera->m_变换.rotation.y = 180;
	camera->m_变换.rotation.z = 0;
	camera->m_isUpdate = true;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_设置激活摄像机为视口摄像机(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);
	//C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);
	//C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	for (auto& ob : S_节点数据::g_选中激活物体) {
		S_摄像机* camera = (S_摄像机*)f_ob_以类型查找子物体(ob, E_物体类型::t_摄像机);
		if (camera) {
			f_ui_set3D视口摄像机(self, camera);
			break;
		}
	}

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体单选(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);
	
	f_工作区_选择物体(工作区页面, false);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体加选(C_Widget* self, uint8 状态) {
	f_projectFile_设置文件保存状态(false);

	C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);

	f_工作区_选择物体(工作区页面, true);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_打开关键帧插入菜单(C_Widget* self, uint8 状态) {
	f_ui_打开菜单(m_3D视口插帧弹出菜单, C_Widget::g_鼠标.gPos);
	return E_事件是否传递::e_事件传递_终止;
}




E_事件是否传递 f_工作区_物体数据编辑(C_Widget* self, uint8 状态) {

	switch (S_框架::g当前编辑对象类型) {
	case E_物体类型::t_网格: {
		switch (f_prop_enum(S_节点数据状态::g_网格编辑模式))
		{
		case E_网格编辑模式::e_网格编辑_顶点: {
			break;
		}
		case E_网格编辑模式::e_网格编辑_权重: {
			std::cout << "刷权重" << std::endl;
			break;
		}
		case E_网格编辑模式::e_网格编辑_纹理: {
			break;
		}
		default:
			break;
		}
		break;
	}
	case E_物体类型::t_骨架:
	case E_物体类型::t_骨骼: {
		if (f_prop_enum(S_节点数据状态::g_骨骼编辑模式)) {
		}
		else {
		}
		break;
	}
	
	case E_物体类型::t_摄像机: {
		break;
	}
	default:
		break;
	}

	return E_事件是否传递::e_事件传递_继续;
}


void f_3D视口工作区_更新视口() {
	if (f_NodeCtx_更新()) {
		f_scene_设置光追渲染器渲染(f_NodeCtx_get默认场景(), true);
		//std::cout << "不更新渲染视口" << std::endl;
		//return false;

		f_NodeCtx_停止更新();
	}
	else {
		f_scene_设置光追渲染器渲染(f_NodeCtx_get默认场景(), false);
		
	}

	if(S_光追后端::g_渲染状态) return;

	for (auto& e : C_3D场景视口::gui_3D视口) {
		if(!e->m_显示) f_ui_3D视口渲染(e);
	}
}


void f_3D视口工作区_保存工作区状态(FILE* f, C_工作区页面* 页面) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(页面->mui_画布页面);
	auto camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	f_写入文件(f, camera->m_变换);
	f_写入文件(f, camera->m_视点);
	f_写入文件(f, camera->m_眼睛偏移);
	f_写入文件(f, camera->m_视点距离);
	f_写入文件(f, camera->m_投影模式);
}

void f_3D视口工作区_加载工作区状态(FILE* f, C_工作区页面* 页面) {
	//ui_3D视口.clear();

	C_3D场景视口* view = static_cast<C_3D场景视口*>(页面->mui_画布页面);
	auto camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	f_读取文件(f, &camera->m_变换);
	f_读取文件(f, &camera->m_视点);
	f_读取文件(f, &camera->m_眼睛偏移);
	f_读取文件(f, &camera->m_视点距离);
	f_读取文件(f, &camera->m_投影模式);

}























//static vec2 g鼠标起始坐标 = {};
//static vec3 g视线向量 = {};
//static vec3 g初始射线终点位置 = {};
//static vec3 g开始射线方向 = {};
//static vec3 g手柄初始位置 = {};
//static std::vector<vec3> g射线(2);
//static std::vector<vec3> g射线_X(2);
//static std::vector<vec3> g射线_Y(2);
//static vec3 g开始射线方向_X = {};
//static vec3 g开始射线方向_Y = {};
//static C_状态条* g当前3D视口状态条 = nullptr;
//static int8 g手柄拾取的轴 = -1;
//static E_变换 g变换方式	= E_变换::e_变换_None;
//static E_轴向 g变换轴	= E_轴向::e_XYZ;
//static bool g变换物体 = false;
//static Mat44f	g相机位置矩阵;
//static Mat44	g相机位置矩阵;












